package com.lsh.payment.core.strategy.query;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lsh.payment.api.model.basevo.ExceptionStatus;
import com.lsh.payment.api.model.payIcp.ApiHead;
import com.lsh.payment.core.constant.BusinessConstant;
import com.lsh.payment.core.exception.BusinessException;
import com.lsh.payment.core.strategy.config.CMBCPayConfig;
import com.lsh.payment.core.strategy.config.IpcPayConfig;
import com.lsh.payment.core.strategy.vo.allinpay.AllinQueryResponse;
import com.lsh.payment.core.strategy.vo.ipcpay.IpcQueryResponse;
import com.lsh.payment.core.util.DateUtil;
import com.lsh.payment.core.util.Idwork.RandomUtil;
import com.lsh.payment.core.util.PayAssert;
import com.lsh.payment.core.util.pay.cmbcpay.Md5SignUtil;
import com.lsh.payment.core.util.pay.cmbcpay.ObjectAndMapConvert;
import com.lsh.payment.core.util.pay.icp.HttpClient431Util;
import com.lsh.payment.core.util.pay.icp.MessageUtil;
import com.lsh.payment.core.util.pay.icp.RsaP1Util;
import com.lsh.payment.core.util.pay.icp.RsaPayUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

/**
 * Project Name: lsh-payment
 * Created by peter on 16/11/6.
 * 北京链商电子商务有限公司
 * Package
 * desc:
 */
@Component
public class IpcQueryStrategy implements QueryStrategy<IpcQueryResponse> {

    private Logger logger = LoggerFactory.getLogger(IpcQueryStrategy.class);

    @Override
    public int getStrategyNo() {
        return BusinessConstant.IPCQUERY;
    }

    /**
     * 查询第三方支付状态
     *
     * @param paramMap 查询参数
     * @return
     */
    @Override
    public IpcQueryResponse queryPayStatusByParams(Map<String, Object> paramMap) {

        logger.info("中投查询:" + JSON.toJSONString(paramMap));

        JSONObject resData = null;
        try {
            //组装报文
            ApiHead head = this.headBuilder(IpcPayConfig.QR1010);

            TreeMap<String, String> params = new TreeMap<>();
            params.put(IpcPayConfig.REQUSET_DATA_BODY_MERID, IpcPayConfig.merid_yg);
            params.put(IpcPayConfig.REQUSET_DATA_BODY_ORIGTRANFLOW, IpcPayConfig.platmerid + "_" + paramMap.get("paymentNo").toString());

            String result = this.requestQr(head, params);

            logger.info("result is " + result);
            JSONObject resMessage;
            //解密得到明文
            String platinText = RsaPayUtil.getPlatinText(result);
//                    new String(rsaP1Util.openMessage(result, IpcPayConfig.merchantPfxPath, "umbpay"));
            logger.info("platinText is " + platinText);
            resMessage = JSON.parseObject(platinText).getJSONObject(IpcPayConfig.REQUSET_MESSAGE);

            //在返回报文明文获取系统返回的签名
            String returnSign = resMessage.getString(IpcPayConfig.REQUSET_MESSAGE_SIGN);
            //重新组装待签名串
            resData = resMessage.getJSONObject(IpcPayConfig.REQUSET_MESSAGE_DATA);
            JSONObject resBody = resData.getJSONObject(IpcPayConfig.REQUSET_MESSAGE_DATA_BODY);
            String buildSign = MessageUtil.getSignStr(resBody.toJSONString());
            //验签
            if (RsaPayUtil.verify(returnSign, buildSign)) {
                //验签成功
                logger.info("验签成功");
            } else {
                //验签失败
                logger.info("验签失败");
                throw new BusinessException("1003002", "验签失败");
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {

        }

        IpcQueryResponse ipcQueryRresponse = this.buildRsp(resData);

        logger.info("请求中投支付,第三方支付流水 返回:" + JSON.toJSONString(ipcQueryRresponse));

        return ipcQueryRresponse;
    }

    /**
     * @param resData
     * @return
     */
    private IpcQueryResponse buildRsp(JSONObject resData) {

        IpcQueryResponse ipcQueryResponse = new IpcQueryResponse();
        ipcQueryResponse.setCode(BusinessConstant.PAY_REQUEST_FAIL);
        ipcQueryResponse.setMsg("中投支付通信失败");

        JSONObject resHead = resData.getJSONObject("head");
        JSONObject resBody = resData.getJSONObject("body");

        ApiHead apiHead = JSON.parseObject(resHead.toJSONString(), ApiHead.class);

        //校验返回参数
        if (apiHead.getRespcode().equals(IpcPayConfig.PAY_STATE_SUCCESS)) {
            ipcQueryResponse = JSON.parseObject(resBody.toJSONString(), IpcQueryResponse.class);

            ipcQueryResponse.setCode(BusinessConstant.PAY_REQUEST_SUCCESS);
            ipcQueryResponse.setApiHead(apiHead);
            ipcQueryResponse.setMsg("中投校验或通信成功");
        } else {

            logger.info("中投返回查询数据有误");
        }

        return ipcQueryResponse;
    }

    private String requestQr(ApiHead head, Map<String, String> channelRequest) {

        RsaP1Util rsaP1Util = new RsaP1Util();
        String result = "";
        try {
            JSONObject outData = new JSONObject();
            JSONObject message = new JSONObject();
            outData.put(IpcPayConfig.REQUSET_MESSAGE, message);
            JSONObject data = new JSONObject();
            message.put(IpcPayConfig.REQUSET_MESSAGE_DATA, data);
            data.put(IpcPayConfig.REQUSET_MESSAGE_DATA_HEAD, head);
            data.put(IpcPayConfig.REQUSET_MESSAGE_DATA_BODY, channelRequest);
            //head和body组装对应的报文
            //生成对应的待签名串 只签名报文体
            String signStr = MessageUtil.getSignStr(JSON.toJSONString(channelRequest));
            //生成签名
            String sign = rsaP1Util.rsaP1Sign(signStr, IpcPayConfig.merchantPfxPath, "umbpay");

            message.put(IpcPayConfig.REQUSET_MESSAGE_SIGN, sign);
            //得到sign后继续组装对应报文，然后加密
            String reqData = outData.toJSONString();
            logger.info("reqData is " + reqData);
            String reqMsg = new String(rsaP1Util.envelopMessage(reqData, IpcPayConfig.publicKeyPath));
            logger.info("reqMsg is " + reqMsg);
            Map<String, String> params = new HashMap<>();
            params.put(IpcPayConfig.REQUSET_DATA, reqMsg);
            params.put(IpcPayConfig.REQUSET_FORMATTYPE, IpcPayConfig.REQUSET_FORMATTYPE_VALUE);
            params.put(IpcPayConfig.REQUSET_CRYPTTYPE, IpcPayConfig.REQUSET_CRYPTTYPE_VALUE);
            params.put(IpcPayConfig.REQUSET_SIGNTYPE, IpcPayConfig.REQUSET_SIGNTYPE_VALUE);
            //发送请求得到结果
            result = HttpClient431Util.doPost(params, IpcPayConfig.url, "UTF-8", "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

    private ApiHead headBuilder(String QRCode) {
        ApiHead head = new ApiHead();

        String clienttime = DateUtil.formatTime(new Date());
        head.setPlatmerid(IpcPayConfig.platmerid);
        head.setTrancode(QRCode);
        head.setTranflow(IpcPayConfig.platmerid + "_" + RandomUtil.snowFlakeId());
        head.setClienttime(clienttime);

        return head;
    }


    private boolean checkPass(Map<String, String> resMap, AllinQueryResponse cmbcQueryResponse) {
        String sign = Md5SignUtil.md5Sign(ObjectAndMapConvert.removeEmptyData(resMap), CMBCPayConfig.KEY);

        PayAssert.notNull(cmbcQueryResponse, ExceptionStatus.E1002002.getCode(), ExceptionStatus.E1002002.getMessage());

        PayAssert.notNull(cmbcQueryResponse.getRetcode(), ExceptionStatus.E1002002.getCode(), ExceptionStatus.E1002002.getMessage());

        PayAssert.notNull(cmbcQueryResponse.getTrxstatus(), ExceptionStatus.E1002002.getCode(), ExceptionStatus.E1002002.getMessage());

        return sign.equals(resMap.get("signOut"));
    }

}
